package org.example.myCustomAnnotation.reflect;

import org.example.myCustomAnnotation.MyComponent;

import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * org.example.myCustomAnnotation.reflect
 *
 * @author 莫磊
 * @description 实现通过注解加载类机制
 * @date 2025/7/27
 */
public class MyComponentReflect {

	/**
	 * 默认加载的包路径，没有值的话就去资源加载器所在路径下的所有类
	 */
	static String loadLocation = "";
	// static String loadLocation = "org.example";

	/**
	 * 初始化的容器
	 */
	static HashMap<String, Object> context = new HashMap<>();

	public static void main (String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, ClassNotFoundException {
		// 转换包路径
		loadLocation = loadLocation.replaceAll("\\.", "/");
		// 获取资源加载器，获取到当前项目所在的位置
		URL resource = ClassLoader.getSystemClassLoader().getResource(loadLocation);
		// 将URL转换为string
		System.out.println(resource.toString());
		// 通过这个路径去加载它下面的所有文件
		File file = new File(resource.getFile());
		// 获取该路径下的所有java文件
		List<File> files = recursionReadFile(file);
		System.out.println(files);

		// 加载file目录下的所有类
		for (File file1 : files) {
			String className = getClassName(file1.getAbsolutePath());
			// 通过类加载器加载类
			Class<?> clazz = Class.forName(className);
			// 判断类是否有MyComponent注解
			for (Annotation declaredAnnotation : clazz.getDeclaredAnnotations()) {
				if (declaredAnnotation instanceof MyComponent && !clazz.isAnnotation()) {
					// 该类使用了MyComponent注解，将其初始化进入容器中
					Object object = clazz.getDeclaredConstructor().newInstance();
					// 判断是否给他设置了默认名
					MyComponent declaredAnnotation1 = clazz.getDeclaredAnnotation(MyComponent.class);
					String value = declaredAnnotation1.value().isEmpty() ? clazz.getSimpleName().substring(0, 1).toLowerCase() + clazz.getSimpleName().substring(1) : declaredAnnotation1.value();
					context.put(value, object);
				}
			}
		}

		System.out.println(context);

	}

	/**
	 * 去除路径中的公共前缀，并且将其转换为类的全路径
	 */
	public static String getClassName(String filePath) {
		// 去除路径中的公共前缀
		String pathStr = filePath.split("classes")[1].split("\\.class")[0];
		// 对象路径进行转换
		pathStr = pathStr.replaceAll("\\\\", "\\.");
		// 返回类的全路径
		return pathStr.startsWith(".") ? pathStr.substring(1) : pathStr;
	}

	/**
	 * 递归查询指定目录下的所有文件
	 */
	public static List<File> recursionReadFile (File file) {
		List<File> fileList = new ArrayList<>();
		// 获取路径下的所有文件列表
		File[] files = file.listFiles();
		for (File file1 : files) {
			if (file1.isDirectory()) {
				// 判断文件是否为文件夹，如果为文件夹是进行递归查询
				fileList.addAll(recursionReadFile(file1));
			} else {
				// 文件不为文件夹，判断是否为.java后缀，是的话加入list,跳过Main类
				if (file1.getAbsolutePath().endsWith(".class") && !file1.getName().equals("Main.class")) {
					fileList.add(file1);
				}
			}
		}
		return fileList;
	}
}
